import React, { Component } from 'react';
import { Button, Input, Card, Row, Col, message, Divider, Typography } from 'antd';
import { CopyOutlined, LockOutlined, UnlockOutlined } from '@ant-design/icons';
import CryptoJS from 'crypto-js';
import forge from 'node-forge';
import styles from './index.less';

const { TextArea } = Input;
const { Title, Text } = Typography;

export default class extends Component {
  constructor(props) {
    super(props);
    this.state = {
      inputText: 'Hello World! ',
      base64Encoded: '',
      base64Decoded: '',
      md5Hash: '',
      sha1Hash: '',
      sha256Hash: '',
      sha512Hash: '',
      aesKey: 'mySecretKey12345',
      aesEncrypted: '',
      aesDecrypted: '',
      desKey: 'myDesKey',
      desEncrypted: '',
      desDecrypted: '',
      tripleDesKey: 'myTripleDesKey123',
      tripleDesEncrypted: '',
      tripleDesDecrypted: '',
      rsaPublicKey: '',
      rsaPrivateKey: '',
      rsaEncrypted: '',
      rsaDecrypted: '',
      rsaLoading: false,
      cryptoSupport: this.checkCryptoSupport(),
    };
  }

  // 检测加密支持情况
  checkCryptoSupport = () => {
    const support = {
      webCrypto: typeof crypto !== 'undefined' && crypto.subtle,
      nodeForge: typeof forge !== 'undefined',
      cryptoJS: typeof CryptoJS !== 'undefined'
    };
    
    console.log('加密库支持情况:', support);
    return support;
  };

  // Base64 编码
  base64Encode = (text) => {
    try {
      return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(text));
    } catch (e) {
      message.error('Base64 编码失败');
      return '';
    }
  };

  // Base64 解码
  base64Decode = (text) => {
    try {
      return CryptoJS.enc.Base64.parse(text).toString(CryptoJS.enc.Utf8);
    } catch (e) {
      message.error('Base64 解码失败');
      return '';
    }
  };

  // MD5 哈希
  md5Hash = (text) => {
    try {
      return CryptoJS.MD5(text).toString();
    } catch (e) {
      message.error('MD5 哈希失败');
      return '';
    }
  };

  // SHA-1 哈希
  sha1Hash = (text) => {
    try {
      return CryptoJS.SHA1(text).toString();
    } catch (e) {
      message.error('SHA-1 哈希失败');
      return '';
    }
  };

  // SHA-256 哈希
  sha256Hash = (text) => {
    try {
      return CryptoJS.SHA256(text).toString();
    } catch (e) {
      message.error('SHA-256 哈希失败');
      return '';
    }
  };

  // SHA-512 哈希
  sha512Hash = (text) => {
    try {
      return CryptoJS.SHA512(text).toString();
    } catch (e) {
      message.error('SHA-512 哈希失败');
      return '';
    }
  };

  // AES 加密
  aesEncrypt = (text, key) => {
    try {
      const encrypted = CryptoJS.AES.encrypt(text, key).toString();
      return encrypted;
    } catch (e) {
      message.error('AES 加密失败');
      return '';
    }
  };

  // AES 解密
  aesDecrypt = (encryptedText, key) => {
    try {
      const decrypted = CryptoJS.AES.decrypt(encryptedText, key).toString(CryptoJS.enc.Utf8);
      return decrypted;
    } catch (e) {
      message.error('AES 解密失败');
      return '';
    }
  };

  // DES 加密
  desEncrypt = (text, key) => {
    try {
      const encrypted = CryptoJS.DES.encrypt(text, key).toString();
      return encrypted;
    } catch (e) {
      message.error('DES 加密失败');
      return '';
    }
  };

  // DES 解密
  desDecrypt = (encryptedText, key) => {
    try {
      const decrypted = CryptoJS.DES.decrypt(encryptedText, key).toString(CryptoJS.enc.Utf8);
      return decrypted;
    } catch (e) {
      message.error('DES 解密失败');
      return '';
    }
  };

  // 3DES 加密
  tripleDesEncrypt = (text, key) => {
    try {
      const encrypted = CryptoJS.TripleDES.encrypt(text, key).toString();
      return encrypted;
    } catch (e) {
      message.error('3DES 加密失败');
      return '';
    }
  };

  // 3DES 解密
  tripleDesDecrypt = (encryptedText, key) => {
    try {
      const decrypted = CryptoJS.TripleDES.decrypt(encryptedText, key).toString(CryptoJS.enc.Utf8);
      return decrypted;
    } catch (e) {
      message.error('3DES 解密失败');
      return '';
    }
  };

  // 生成 RSA 密钥对（使用 node-forge 1.3.1）
  generateRSAKeys = () => {
    this.setState({ rsaLoading: true });
    try {
      // 生成 RSA 密钥对，使用较小的密钥长度以提高兼容性
      const keyPair = forge.pki.rsa.generateKeyPair(1024);
      
      // 导出公钥为 PEM 格式
      const publicKeyPem = forge.pki.publicKeyToPem(keyPair.publicKey);
      
      // 导出私钥为 PEM 格式
      const privateKeyPem = forge.pki.privateKeyToPem(keyPair.privateKey);

      console.log('密钥对生成成功');
      console.log('公钥长度:', publicKeyPem.length);
      console.log('私钥长度:', privateKeyPem.length);

      this.setState({
        rsaPublicKey: publicKeyPem,
        rsaPrivateKey: privateKeyPem,
        rsaKeyPair: keyPair,
        rsaLoading: false
      });

      message.success('RSA 密钥对生成成功（1024位）');
    } catch (e) {
      this.setState({ rsaLoading: false });
      console.error('密钥对生成失败:', e);
      message.error('RSA 密钥对生成失败: ' + e.message);
    }
  };

  // RSA 加密（使用 node-forge）
  rsaEncrypt = (text) => {
    try {
      if (!this.state.rsaKeyPair) {
        message.error('请先生成 RSA 密钥对');
        return '';
      }

      // 验证输入文本
      if (!text || text.trim() === '') {
        message.error('请输入要加密的文本');
        return '';
      }

      // 计算文本的实际字节长度（中文占3个字节）
      const textBytes = new TextEncoder().encode(text).length;
      console.log('文本字符长度:', text.length);
      console.log('文本字节长度:', textBytes);
      
      // 检查字节长度（RSA 1024位密钥最多加密 117 字节）
      if (textBytes > 117) {
        message.warning(`RSA 加密文本过长，当前 ${textBytes} 字节，建议少于 100 字节`);
        return '';
      }

      // 使用默认填充模式，不指定任何参数
      const encrypted = this.state.rsaKeyPair.publicKey.encrypt(text);
      
      // 验证加密结果
      if (!encrypted || encrypted.length === 0) {
        message.error('加密结果为空');
        return '';
      }

      // 转换为 Base64
      const base64Result = forge.util.encode64(encrypted);
      console.log('RSA 加密成功，结果长度:', base64Result.length);
      console.log('使用的公钥:', this.state.rsaKeyPair.publicKey.n.toString(16).substring(0, 20) + '...');
      
      return base64Result;
    } catch (e) {
      console.error('RSA 加密详细错误:', e);
      message.error('RSA 加密失败: ' + e.message);
      return '';
    }
  };

  // RSA 解密（使用 node-forge）
  rsaDecrypt = (encryptedText) => {
    try {
      if (!this.state.rsaKeyPair) {
        message.error('请先生成 RSA 密钥对');
        return '';
      }

      // 验证加密文本格式
      if (!encryptedText || encryptedText.trim() === '') {
        message.error('加密文本为空');
        return '';
      }

      console.log('开始解密，加密文本长度:', encryptedText.length);
      console.log('当前密钥对存在:', !!this.state.rsaKeyPair);
      console.log('公钥存在:', !!this.state.rsaKeyPair.publicKey);
      console.log('私钥存在:', !!this.state.rsaKeyPair.privateKey);

      // 从 Base64 解码
      let encrypted;
      try {
        encrypted = forge.util.decode64(encryptedText);
        console.log('Base64 解码成功，数据长度:', encrypted.length);
      } catch (decodeError) {
        console.error('Base64 解码失败:', decodeError);
        message.error('Base64 解码失败: ' + decodeError.message);
        return '';
      }

      // 验证解码后的数据
      if (!encrypted || encrypted.length === 0) {
        message.error('解码后的数据为空');
        return '';
      }

      // 检查密钥对是否匹配
      if (!this.state.rsaKeyPair.privateKey) {
        message.error('私钥不存在，请重新生成密钥对');
        return '';
      }

      // 使用默认填充模式，不指定任何参数
      const decrypted = this.state.rsaKeyPair.privateKey.decrypt(encrypted);
      console.log('解密成功，结果:', decrypted);
      console.log('使用的私钥:', this.state.rsaKeyPair.privateKey.n.toString(16).substring(0, 20) + '...');
      
      return decrypted;
    } catch (e) {
      console.error('RSA 解密详细错误:', e);
      console.error('错误堆栈:', e.stack);
      console.error('错误类型:', e.name);
      console.error('错误消息:', e.message);
      
      // 根据错误类型给出更具体的提示
      if (e.message.includes('Encryption block is invalid')) {
        message.error('解密失败：加密块无效，可能是填充模式不匹配或密钥不匹配');
      } else if (e.message.includes('Invalid padding')) {
        message.error('解密失败：填充无效，请检查加密和解密是否使用相同的填充模式');
      } else {
        message.error('RSA 解密失败: ' + e.message);
      }
      return '';
    }
  };

  // 复制到剪贴板
  copyToClipboard = (text) => {
    navigator.clipboard.writeText(text).then(() => {
      message.success('已复制到剪贴板');
    }).catch(() => {
      message.error('复制失败');
    });
  };

  // 处理输入变化
  handleInputChange = (e) => {
    this.setState({ inputText: e.target.value });
  };

  handleAesKeyChange = (e) => {
    this.setState({ aesKey: e.target.value });
  };

  handleDesKeyChange = (e) => {
    this.setState({ desKey: e.target.value });
  };

  handleTripleDesKeyChange = (e) => {
    this.setState({ tripleDesKey: e.target.value });
  };

  // 执行所有加密操作
  performAllEncryptions = () => {
    const { inputText, aesKey, desKey, tripleDesKey } = this.state;
    
    // Base64
    const base64Encoded = this.base64Encode(inputText);
    const base64Decoded = this.base64Decode(base64Encoded);
    
    // 哈希
    const md5Hash = this.md5Hash(inputText);
    const sha1Hash = this.sha1Hash(inputText);
    const sha256Hash = this.sha256Hash(inputText);
    const sha512Hash = this.sha512Hash(inputText);
    
    // AES
    const aesEncrypted = this.aesEncrypt(inputText, aesKey);
    const aesDecrypted = this.aesDecrypt(aesEncrypted, aesKey);
    
    // DES
    const desEncrypted = this.desEncrypt(inputText, desKey);
    const desDecrypted = this.desDecrypt(desEncrypted, desKey);
    
    // 3DES
    const tripleDesEncrypted = this.tripleDesEncrypt(inputText, tripleDesKey);
    const tripleDesDecrypted = this.tripleDesDecrypt(tripleDesEncrypted, tripleDesKey);
    
    this.setState({
      base64Encoded,
      base64Decoded,
      md5Hash,
      sha1Hash,
      sha256Hash,
      sha512Hash,
      aesEncrypted,
      aesDecrypted,
      desEncrypted,
      desDecrypted,
      tripleDesEncrypted,
      tripleDesDecrypted
    });
  };

  render() {
    const {
      inputText,
      base64Encoded,
      base64Decoded,
      md5Hash,
      sha1Hash,
      sha256Hash,
      sha512Hash,
      aesKey,
      aesEncrypted,
      aesDecrypted,
      desKey,
      desEncrypted,
      desDecrypted,
      tripleDesKey,
      tripleDesEncrypted,
      tripleDesDecrypted,
      rsaPublicKey,
      rsaPrivateKey,
      rsaEncrypted,
      rsaDecrypted,
      rsaLoading,
      cryptoSupport
    } = this.state;

    return (
      <div className={styles.container}>
        <Title level={2}>🔐 JavaScript 加密解密示例</Title>
        
        {/* 输入区域 */}
        <Card title="📝 输入文本" className={styles.card}>
          <TextArea
            value={inputText}
            onChange={this.handleInputChange}
            placeholder="请输入要加密的文本"
            rows={4}
          />
          <div className={styles.buttonGroup}>
            <Button 
              type="primary" 
              icon={<LockOutlined />}
              onClick={this.performAllEncryptions}
            >
              执行所有加密
            </Button>
          </div>
        </Card>

        <Row gutter={[16, 16]}>
          {/* Base64 编码解码 */}
          <Col xs={24} lg={12}>
            <Card title="Base64 编码/解码" className={styles.card}>
              <div className={styles.resultItem}>
                <Text strong>编码结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{base64Encoded}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(base64Encoded)}
                  />
                </div>
              </div>
              <div className={styles.resultItem}>
                <Text strong>解码结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{base64Decoded}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(base64Decoded)}
                  />
                </div>
              </div>
            </Card>
          </Col>

          {/* 哈希函数 */}
          <Col xs={24} lg={12}>
            <Card title="哈希函数" className={styles.card}>
              <div className={styles.resultItem}>
                <Text strong>MD5：</Text>
                <div className={styles.resultBox}>
                  <Text code>{md5Hash}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(md5Hash)}
                  />
                </div>
              </div>
              <div className={styles.resultItem}>
                <Text strong>SHA-1：</Text>
                <div className={styles.resultBox}>
                  <Text code>{sha1Hash}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(sha1Hash)}
                  />
                </div>
              </div>
              <div className={styles.resultItem}>
                <Text strong>SHA-256：</Text>
                <div className={styles.resultBox}>
                  <Text code>{sha256Hash}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(sha256Hash)}
                  />
                </div>
              </div>
              <div className={styles.resultItem}>
                <Text strong>SHA-512：</Text>
                <div className={styles.resultBox}>
                  <Text code>{sha512Hash}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(sha512Hash)}
                  />
                </div>
              </div>
            </Card>
          </Col>

          {/* AES 对称加密 */}
          <Col xs={24} lg={12}>
            <Card title="AES 对称加密" className={styles.card}>
              <div className={styles.resultItem}>
                <Text strong>密钥：</Text>
                <Input
                  value={aesKey}
                  onChange={this.handleAesKeyChange}
                  placeholder="输入 AES 密钥"
                />
              </div>
              <div className={styles.resultItem}>
                <Text strong>加密结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{aesEncrypted}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(aesEncrypted)}
                  />
                </div>
              </div>
              <div className={styles.resultItem}>
                <Text strong>解密结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{aesDecrypted}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(aesDecrypted)}
                  />
                </div>
              </div>
            </Card>
          </Col>

          {/* DES 对称加密 */}
          <Col xs={24} lg={12}>
            <Card title="DES 对称加密" className={styles.card}>
              <div className={styles.resultItem}>
                <Text strong>密钥：</Text>
                <Input
                  value={desKey}
                  onChange={this.handleDesKeyChange}
                  placeholder="输入 DES 密钥"
                />
              </div>
              <div className={styles.resultItem}>
                <Text strong>加密结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{desEncrypted}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(desEncrypted)}
                  />
                </div>
              </div>
              <div className={styles.resultItem}>
                <Text strong>解密结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{desDecrypted}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(desDecrypted)}
                  />
                </div>
              </div>
            </Card>
          </Col>

          {/* 3DES 对称加密 */}
          <Col xs={24} lg={12}>
            <Card title="3DES 对称加密" className={styles.card}>
              <div className={styles.resultItem}>
                <Text strong>密钥：</Text>
                <Input
                  value={tripleDesKey}
                  onChange={this.handleTripleDesKeyChange}
                  placeholder="输入 3DES 密钥"
                />
              </div>
              <div className={styles.resultItem}>
                <Text strong>加密结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{tripleDesEncrypted}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(tripleDesEncrypted)}
                  />
                </div>
              </div>
              <div className={styles.resultItem}>
                <Text strong>解密结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{tripleDesDecrypted}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(tripleDesDecrypted)}
                  />
                </div>
              </div>
            </Card>
          </Col>

          {/* RSA 非对称加密 */}
          <Col xs={24} lg={12}>
            <Card title="RSA 非对称加密" className={styles.card}>
              <div style={{ marginBottom: 16, padding: 8, background: '#f0f9ff', border: '1px solid #bae6fd', borderRadius: 6 }}>
                <Text type="secondary" style={{ fontSize: 12 }}>
                  💡 提示：RSA 1024位密钥加密有字节长度限制（中文占3字节，建议少于 30 个中文字符），长文本建议使用 AES 对称加密
                </Text>
                <br />
                <Text type="secondary" style={{ fontSize: 12 }}>
                  🔑 操作顺序：1. 生成密钥对 → 2. 加密 → 3. 解密（必须使用同一密钥对）
                </Text>
              </div>
              <div className={styles.buttonGroup}>
                <Button 
                  type="primary" 
                  loading={rsaLoading}
                  onClick={this.generateRSAKeys}
                >
                  {rsaLoading ? '生成中...' : '生成密钥对'}
                </Button>
                <Button 
                  disabled={!rsaPublicKey}
                  onClick={() => {
                    this.setState({ rsaLoading: true });
                    console.log('手动加密，输入文本:', inputText);
                    console.log('输入文本长度:', inputText.length);
                    const encrypted = this.rsaEncrypt(inputText);
                    console.log('手动加密结果:', encrypted);
                    if (encrypted) {
                      this.setState({ rsaEncrypted: encrypted, rsaLoading: false });
                      message.success('加密成功');
                    } else {
                      this.setState({ rsaLoading: false });
                      message.error('加密失败');
                    }
                  }}
                >
                  加密
                </Button>
                <Button 
                  disabled={!rsaEncrypted}
                  onClick={() => {
                    this.setState({ rsaLoading: true });
                    console.log('手动解密，加密文本:', rsaEncrypted);
                    console.log('加密文本长度:', rsaEncrypted.length);
                    const decrypted = this.rsaDecrypt(rsaEncrypted);
                    console.log('手动解密结果:', decrypted);
                    if (decrypted) {
                      this.setState({ rsaDecrypted: decrypted, rsaLoading: false });
                      message.success('解密成功');
                    } else {
                      this.setState({ rsaLoading: false });
                      message.error('解密失败');
                    }
                  }}
                >
                  解密
                </Button>
                <Button 
                  onClick={() => {
                    this.setState({ rsaLoading: true });
                    const testText = 'A';
                    console.log('开始测试，原文:', testText);
                    const encrypted = this.rsaEncrypt(testText);
                    console.log('加密结果:', encrypted);
                    if (encrypted) {
                      const decrypted = this.rsaDecrypt(encrypted);
                      console.log('解密结果:', decrypted);
                      this.setState({ 
                        rsaEncrypted: encrypted, 
                        rsaDecrypted: decrypted,
                        rsaLoading: false 
                      });
                      message.success(`测试完成！原文: ${testText}, 解密: ${decrypted}`);
                    } else {
                      this.setState({ rsaLoading: false });
                      message.error('加密失败');
                    }
                  }}
                >
                  测试
                </Button>
              </div>
              
              {rsaPublicKey && (
                <div className={styles.resultItem}>
                  <Text strong>公钥：</Text>
                  <div className={styles.resultBox}>
                    <Text code className={styles.longText}>
                      {rsaPublicKey.length > 100 
                        ? `${rsaPublicKey.substring(0, 50)}...${rsaPublicKey.substring(rsaPublicKey.length - 50)}`
                        : rsaPublicKey
                      }
                    </Text>
                    <Button 
                      size="small" 
                      icon={<CopyOutlined />}
                      onClick={() => this.copyToClipboard(rsaPublicKey)}
                      title="复制完整公钥"
                    />
                  </div>
                </div>
              )}
              
              {rsaPrivateKey && (
                <div className={styles.resultItem}>
                  <Text strong>私钥：</Text>
                  <div className={styles.resultBox}>
                    <Text code className={styles.longText}>
                      {rsaPrivateKey.length > 100 
                        ? `${rsaPrivateKey.substring(0, 50)}...${rsaPrivateKey.substring(rsaPrivateKey.length - 50)}`
                        : rsaPrivateKey
                      }
                    </Text>
                    <Button 
                      size="small" 
                      icon={<CopyOutlined />}
                      onClick={() => this.copyToClipboard(rsaPrivateKey)}
                      title="复制完整私钥"
                    />
                  </div>
                </div>
              )}
              
              <div className={styles.resultItem}>
                <Text strong>加密结果：</Text>
                <div className={styles.resultBox}>
                  <Text code className={styles.longText}>{rsaEncrypted}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(rsaEncrypted)}
                  />
                </div>
              </div>
              
              <div className={styles.resultItem}>
                <Text strong>解密结果：</Text>
                <div className={styles.resultBox}>
                  <Text code>{rsaDecrypted}</Text>
                  <Button 
                    size="small" 
                    icon={<CopyOutlined />}
                    onClick={() => this.copyToClipboard(rsaDecrypted)}
                  />
                </div>
              </div>
            </Card>
          </Col>
        </Row>
      </div>
    );
  }
}